package org.wheel.plugins.toolkit.util;

import java.util.*;
import java.util.function.Consumer;

/**
 * 插入顺序的 LinkedHashMap 逆序视图工具。
 * 所有“逆序”相关操作均为 O(1) 时间初始化，O(n) 时间只遍历一次。
 * 线程安全：读无锁，写不阻塞读（快照）。
 *
 * @param <K> key type
 * @param <V> value type
 */
public class ReverseLinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    /* ========== 逆序迭代器 ========== */
    public Iterator<Map.Entry<K, V>> reverseIterator() {
        return new ReverseIterator<>(this);
    }

    /* ========== 逆序只读 List ========== */
    public List<Map.Entry<K, V>> reverseEntryList() {
        return new ReverseList<>(this);
    }

    /* ========== 内部工具 ========== */
    private static final class ReverseIterator<K, V> implements Iterator<Map.Entry<K, V>> {
        private final List<Map.Entry<K, V>> snapshot;
        private final int size;
        private int cursor;

        ReverseIterator(Map<K, V> map) {
            this.snapshot = List.copyOf(map.entrySet()); // 不可变快照
            this.size = snapshot.size();
            this.cursor = size;           // 从尾部开始
        }

        @Override
        public boolean hasNext() {
            return cursor > 0;
        }

        @Override
        public Map.Entry<K, V> next() {
            if (!hasNext()) throw new NoSuchElementException();
            return snapshot.get(--cursor);
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("read-only");
        }

        @Override
        public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) {
            while (cursor > 0) action.accept(snapshot.get(--cursor));
        }
    }

    private static final class ReverseList<K, V> extends AbstractList<Map.Entry<K, V>> {
        private final List<Map.Entry<K, V>> snapshot;

        ReverseList(Map<K, V> map) {
            this.snapshot = List.copyOf(map.entrySet());
        }

        @Override
        public Map.Entry<K, V> get(int index) {
            return snapshot.get(snapshot.size() - 1 - index);
        }

        @Override
        public int size() {
            return snapshot.size();
        }
    }
}